home *** CD-ROM | disk | FTP | other *** search
Oberon Text | 1991-02-15 | 9.3 KB | 192 lines | [.Ob./.Ob2] |
- Syntax10.Scn.Fnt
- MODULE PopupElems; (* Michael Franz, 20.11.90 -- "Hypertext without Surprises" *)
- IMPORT
- Oberon, Input, Display, Viewers, Files, Fonts, Printer, Texts, TextFrames, MenuViewers, WriteTexts, WriteFrames, WriteParcs;
- CONST
- CR=0DX;
- edw=4; edh=2; mdw=3; mdh=1;
- ElemFont="Syntax12m.Scn.Fnt";
- EditMenu="System.Close System.Grow";
- TYPE
- PopupElem=POINTER TO PopupElemDesc;
- PopupElemDesc=RECORD (WriteTexts.ElemDesc)
- name: ARRAY 32 OF CHAR;
- menu: Texts.Text;
- dft, w, lin, min, n: INTEGER
- END;
- EditFrame=POINTER TO EditFrameDesc;
- EditFrameDesc=RECORD (TextFrames.FrameDesc)
- elem: PopupElem
- END;
- buf: Texts.Buffer;
- elfnt: Fonts.Font; (* font of element box text *)
- lsp, loff, marg: INTEGER; (* line space, line offset, window margin *)
- (* auxiliary *)
- PROCEDURE Min(x, y: INTEGER): INTEGER;
- BEGIN IF x<y THEN RETURN x ELSE RETURN y END
- END Min;
- PROCEDURE Max(x, y: INTEGER): INTEGER;
- BEGIN IF x>y THEN RETURN x ELSE RETURN y END
- END Max;
- (* internal consistency *)
- PROCEDURE SetupMenu(E: PopupElem);
- VAR ch: CHAR; w, pdx, px, py, pw, ph: INTEGER; pat: LONGINT; r: Texts.Reader;
- BEGIN Texts.OpenReader(r, E.menu, 0); E.w:=0; E.n:=1; E.lin:=0; w:=0;
- LOOP Texts.Read(r, ch);
- IF r.eot THEN E.w:=Max(E.w, w); E.dft:=Min(E.dft, E.n); RETURN
- ELSIF ch=CR THEN E.w:=Max(E.w, w); w:=0; INC(E.n)
- ELSE E.lin:=Max(E.lin, r.fnt.height); E.min:=Min(E.min, r.fnt.minY);
- Display.GetChar(r.fnt.raster, ch, pdx, px, py, pw, ph, pat); INC(w, pdx)
- END
- END
- END SetupMenu;
- PROCEDURE SetupElem(E: PopupElem; s: ARRAY OF CHAR);
- VAR ch: CHAR; i, w, pdx, px, py, pw, ph: INTEGER; pat: LONGINT;
- BEGIN i:=0; w:=2*edw+4;
- LOOP ch:=s[i]; E.name[i]:=ch;
- IF ch=0X THEN E.DX:=(w+1)*Display.Unit; E.W:=w*Display.Unit; E.H:=(lsp+2*edh+2)*Display.Unit; EXIT
- ELSE Display.GetChar(elfnt.raster, ch, pdx, px, py, pw, ph, pat); INC(w, pdx); INC(i) END
- END
- END SetupElem;
- (* interactive editing of popup menus *)
- PROCEDURE* EditHandle(F: Display.Frame; VAR msg: Display.FrameMsg);
- BEGIN
- WITH F: EditFrame DO TextFrames.Handle(F, msg);
- IF ((msg IS Oberon.InputMsg)&(msg(Oberon.InputMsg).id=Oberon.consume)) OR (msg IS TextFrames.UpdateMsg)
- THEN SetupMenu(F.elem) END
- END
- END EditHandle;
- PROCEDURE EditOpen(E: PopupElem);
- VAR x, y: INTEGER; V: Viewers.Viewer; F: EditFrame;
- BEGIN Oberon.AllocateUserViewer(Oberon.Par.vwr.X, x, y); NEW(F); F.elem:=E;
- TextFrames.Open(F, EditHandle, E.menu, 0, Display.black, TextFrames.menuH+marg, marg, marg, marg, 0);
- V:=MenuViewers.New(TextFrames.NewMenu(E.name, EditMenu), F, TextFrames.menuH, x, y)
- END EditOpen;
- (* file input/output *)
- PROCEDURE Load(VAR r: Files.Rider; E: PopupElem);
- VAR i: INTEGER; pos, len: LONGINT; f: Files.File; s: ARRAY 32 OF CHAR; ch: CHAR;
- BEGIN i:=0; REPEAT Files.Read(r, ch); s[i]:=ch; INC(i) UNTIL ch=0X; s[i-1]:="."; s[i]:="."; s[i+1]:="."; s[i+2]:=0X;
- Files.Read(r, ch); E.dft:=ORD(ch); SetupElem(E, s); E.menu:=TextFrames.Text("");
- pos:=Files.Pos(r)+2; f:=Files.Base(r); Texts.Load(E.menu, f, pos, len); Files.Set(r, f, pos+len)
- END Load;
- PROCEDURE StoreString(VAR r: Files.Rider; s: ARRAY OF CHAR);
- VAR i: INTEGER;
- BEGIN i:=0; WHILE s[i] # 0X DO INC(i) END; Files.WriteBytes(r, s, i-3); Files.Write(r, 0X)
- END StoreString;
- PROCEDURE Store(VAR r: Files.Rider; E: PopupElem);
- VAR pos, len: LONGINT; f: Files.File;
- BEGIN StoreString(r, "PopupElems.Alloc..."); StoreString(r, E.name); Files.Write(r, CHR(E.dft MOD 128));
- pos:=Files.Pos(r); f:=Files.Base(r); len:=E.menu.len; Texts.Store(E.menu, f, pos, len); Files.Set(r, f, pos+len)
- END Store;
- (* graphics *)
- PROCEDURE Box(x, y, w, h: INTEGER);
- BEGIN
- Display.ReplConst(Display.white, x, y, w, 2, Display.replace);
- Display.ReplConst(Display.white, x, y+h-2, w, 2, Display.replace);
- Display.ReplConst(Display.white, x, y+2, 2, h-4, Display.replace);
- Display.ReplConst(Display.white, x+w-2, y+2, 2, h-4, Display.replace);
- Display.ReplConst(Display.black, x+2, y+2, w-4, h-4, Display.replace)
- END Box;
- PROCEDURE PrintElem(E: PopupElem; x, y, w, h: INTEGER);
- BEGIN Printer.ReplConst(x, y, w, 2); Printer.ReplConst(x, y+h-2, w, 2);
- Printer.ReplConst(x, y+2, 2, h-4); Printer.ReplConst(x+w-2, y+2, 2, h-4);
- Printer.String(x+edw+2, y+edh+2+loff, E.name, elfnt)
- END PrintElem;
- PROCEDURE DrawElem(E: PopupElem; x, y, w, h: INTEGER);
- VAR i, pdx, px, py, pw, ph: INTEGER; pat: LONGINT;
- BEGIN Box(x, y, w, h); INC(x, edw+2); INC(y, edh+2-loff); i:=0;
- WHILE E.name[i] >= " " DO Display.GetChar(elfnt.raster, E.name[i], pdx, px, py, pw, ph, pat);
- Display.CopyPattern(Display.white, pat, x+px, y+py, Display.replace); INC(x, pdx); INC(i)
- END
- END DrawElem;
- PROCEDURE DrawMenu(E: PopupElem; x, y, w, h: INTEGER);
- VAR xl, pdx, px, py, pw, ph: INTEGER; pat: LONGINT; r: Texts.Reader; ch: CHAR;
- BEGIN Box(x, y, w, h); Texts.OpenReader(r, E.menu, 0); xl:=x+mdw+2; x:=xl; y:=y+h-E.lin-E.min-mdh-2;
- LOOP Texts.Read(r, ch);
- IF r.eot THEN RETURN
- ELSIF ch=CR THEN y:=y-E.lin; x:=xl
- ELSE Display.GetChar (r.fnt.raster, ch, pdx, px, py, pw, ph, pat);
- Display.CopyPattern(Display.white, pat, x+px, y+py, Display.replace); INC(x, pdx)
- END
- END
- END DrawMenu;
- (* actions *)
- PROCEDURE Show(E: PopupElem; x, y, w, h: INTEGER; VAR cmd: INTEGER);
- VAR mx, my, top, bot, left, right, newCmd: INTEGER; keys: SET;
- BEGIN left:=x+3; right:=x+w-3; bot:=y+mdh+3; top:=y+h-mdh-2; Oberon.RemoveMarks(x, y, w, h);
- Oberon.FadeCursor(Oberon.Mouse); Display.CopyBlock(x, y, w, h, x, -h, Display.replace);
- DrawMenu(E, x, y, w, h); Display.ReplConst(Display.white, x+3, top-cmd*E.lin-E.lin, w-6, E.lin, Display.invert);
- REPEAT Input.Mouse(keys, mx, my); Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, mx, my);
- IF keys * {0, 2} # {} THEN Oberon.FadeCursor(Oberon.Mouse); Display.CopyBlock(x, -h, w, h, x, y, Display.replace);
- IF 0 IN keys THEN EditOpen(E) END;
- REPEAT Input.Mouse(keys, mx, my); Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, mx, my) UNTIL keys={};
- cmd:=-1; RETURN
- ELSIF (mx>=left) & (mx<=right) & (my>=bot) & (my<=top) THEN newCmd:=(top-my) DIV E.lin;
- IF newCmd # cmd THEN
- IF cmd # -1 THEN Display.ReplConst(Display.white, x+3, top-cmd*E.lin-E.lin, w-6, E.lin, Display.invert) END;
- Display.ReplConst(Display.white, x+3, top-newCmd*E.lin-E.lin, w-6, E.lin, Display.invert); cmd:=newCmd
- END
- ELSIF cmd # -1 THEN
- Display.ReplConst(Display.white, x+3, top-cmd*E.lin-E.lin, w-6, E.lin, Display.invert); cmd:=-1
- END
- UNTIL keys={};
- Oberon.FadeCursor(Oberon.Mouse); Display.CopyBlock(x, -h, w, h, x, y, Display.replace);
- END Show;
- PROCEDURE Popup(E: PopupElem; x, y: INTEGER);
- VAR mx, my, w, h, i, j, cmd, res: INTEGER; cmdStr: ARRAY 32 OF CHAR; r: Texts.Reader; ch: CHAR; keys: SET;
- BEGIN Input.Mouse(keys, mx, my); w:=E.w+2*mdw+4; h:=E.n*E.lin+2*mdh+4;
- y:=Max(my-h+E.lin+E.dft*E.lin, 0); cmd:=E.dft;
- IF x+w > Display.Width THEN x:=Display.Width-w END;
- IF y+h > Display.Height THEN y:=Display.Height-h END;
- Show(E, x, y, w, h, cmd);
- IF cmd > -1 THEN E.dft:=cmd; j:=0; Texts.OpenReader(r, E.menu, 0); Texts.Read(r, ch);
- WHILE j < cmd DO IF ch=CR THEN INC(j) END; Texts.Read(r, ch) END;
- i:=0; WHILE (ch>" ") & (ch#CR) & (i<32) DO cmdStr[i]:=ch; INC(i); Texts.Read(r, ch) END; cmdStr[i]:=0X;
- Oberon.Par.vwr:=Viewers.This(x, y); Oberon.Par.frame:=Oberon.Par.vwr.dsc;
- Oberon.Par.text:=E.menu; Oberon.Par.pos:=Texts.Pos(r); Oberon.Call(cmdStr, Oberon.Par, FALSE, res)
- END
- END Popup;
- (* element *)
- PROCEDURE* Handle(E: WriteTexts.Elem; VAR msg: Display.FrameMsg);
- VAR e: PopupElem;
- BEGIN
- WITH E: PopupElem DO
- IF msg IS WriteTexts.DrawMsg THEN
- WITH msg: WriteTexts.DrawMsg DO
- DrawElem(E, msg.X0, msg.Y0, SHORT(E.W DIV msg.unit), SHORT(E.H DIV msg.unit));
- END
- ELSIF msg IS WriteTexts.PrintMsg THEN
- WITH msg: WriteTexts.PrintMsg DO
- PrintElem(E, msg.X0, msg.Y0, SHORT(E.W DIV msg.unit), SHORT(E.H DIV msg.unit))
- END
- ELSIF msg IS WriteTexts.LoadMsg THEN Load(msg(WriteTexts.LoadMsg).r, E); SetupMenu(E)
- ELSIF msg IS WriteTexts.StoreMsg THEN Store(msg(WriteTexts.StoreMsg).r, E)
- ELSIF msg IS WriteTexts.CopyMsg THEN
- WITH msg: WriteTexts.CopyMsg DO
- IF msg.e=NIL THEN NEW(e); msg.e:=e ELSE e:=msg.e(PopupElem) END;
- e.name:=E.name; e.dft:=E.dft; e.w:=E.w; e.lin:=E.lin; e.min:=E.min; e.n:=E.n;
- e.menu:=TextFrames.Text(""); Texts.Save(E.menu, 0, E.menu.len, buf); Texts.Append(e.menu, buf)
- END
- ELSIF msg IS WriteFrames.TrackMsg THEN
- WITH msg: WriteFrames.TrackMsg DO
- IF msg.keys={1} THEN Popup(E, msg.X0, msg.Y0) END
- END
- END
- END
- END Handle;
- PROCEDURE Alloc*;
- VAR e: PopupElem;
- BEGIN NEW(e); e.handle:=Handle; Oberon.Par(WriteTexts.AllocPar).e:=e
- END Alloc;
- PROCEDURE Insert*;
- VAR E: PopupElem; S: Texts.Scanner; T: WriteTexts.Text; M: Oberon.CopyOverMsg;
- BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
- IF S.class #Texts.String THEN S.s:="Popup" END;
- NEW(E); SetupElem(E, S.s); E.menu:=TextFrames.Text(""); SetupMenu(E);
- WriteTexts.OpenElem(E, Handle, E.DX, E.W, E.H);
- T:=WriteFrames.Text("", WriteParcs.defParc); WriteTexts.AppendElem(T, E);
- M.text:=T; M.beg:=0; M.end:=T.len; Oberon.FocusViewer.handle(Oberon.FocusViewer, M)
- END Insert;
- BEGIN elfnt:=Fonts.This(ElemFont); lsp:=elfnt.height+edh; loff:=elfnt.minY; marg:=Fonts.Default.height DIV 2; NEW(buf); Texts.OpenBuf(buf)
- END PopupElems.
-